package com.demo.vert.io;

import io.vertx.core.Vertx;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetSocket;
import lombok.extern.java.Log;

import java.util.concurrent.atomic.AtomicReference;

@Log
public class VertxServerProxy {
    private static final int LOCAL_PORT = 13306;
    private static final int REMOTE_PORT = 3306;
    private static final String REMOTE_HOST = "localhost";

    public static void main(String[] args) {
        NetServer server = Vertx.vertx().createNetServer();
        server.connectHandler(netSocket -> {
            log.info("Server 拿到NetSocket"+netSocket);
            /*netSocket.handler(data -> {
               log.info(data.toString());
            });
            netSocket.exceptionHandler(event -> {
                log.info("Server发生异常！");
                event.printStackTrace();
            });
            netSocket.closeHandler( v ->{
                log.info("Server连接断开");
            });
            netSocket.drainHandler( v->{
               log.info("写队列ok，继续处理缓冲区数据！");
            });*/
            getNetClient(netSocket);
        });
        server.listen(LOCAL_PORT,res -> {
            if(res.succeeded()) {
                log.info("Server 启动成功！");
            }else {
                log.info("Server 启动失败！");
                res.cause().printStackTrace();
            }
        });



       /* new Thread( () -> {
            try {
                Thread.sleep(60000);
                log.info("60秒到了，准备关闭服务器和客户端！");
                server.close(res -> {
                    log.info("关闭服务！");
                });
                client.close( v -> {
                    log.info("断开客户端连接");
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();*/



    }

    private static NetClient getNetClient(NetSocket serverSocket) {
        AtomicReference<NetSocket> clientSocket = new AtomicReference<>();
        log.info("创建客户端！");
        NetClient client = Vertx.vertx().createNetClient();
        client.connect(REMOTE_PORT,REMOTE_HOST,res -> {
            if(res.succeeded()) {
                log.info("Client 连接"+REMOTE_HOST+":"+REMOTE_PORT+"成功！");
            }else {
                log.info("Client 连接"+REMOTE_HOST+":"+REMOTE_PORT+"失败！");
                res.cause().printStackTrace();
                closeNetSocket(serverSocket);
            }
            NetSocket result = res.result();
            log.info("Client拿到NetSocket:"+result);
            result.closeHandler(event -> {
                log.info("Client 断开了连接");
                closeNetSocket(serverSocket);
            });
            //可不提供
            result.drainHandler( event ->  {
                log.info("Client 写队列ok，继续处理缓冲区数据！");
                result.resume();
            });
            result.exceptionHandler(event -> {
                log.info("Client 发生了异常！");
                closeNetSocket(serverSocket);
            });
            // 客户端接收的数据发送给服务端
            result.handler(recData -> {
                log.info("Client 接收数据："+recData.toString());
                serverSocket.write(recData);
            });
            clientSocket.set(result);

        });

        serverSocket.exceptionHandler(event -> {
            log.info("Server发生异常！");
            event.printStackTrace();
            closeNetSocket(clientSocket.get());
        });
        serverSocket.closeHandler( v ->{
            log.info("Server连接断开");
            closeNetSocket(clientSocket.get());
        });
        //可不提供
        serverSocket.drainHandler( v->{
            log.info("Server 写队列ok，继续处理缓冲区数据！");
            serverSocket.resume();
        });
        // 服务端接收到数据响应给客户端
        serverSocket.handler(recData -> {
            log.info("Server 收到信息："+recData);
            while ( clientSocket.get() ==null)
            {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            clientSocket.get().write(recData);
        });
        return client;
    }
    static void closeNetSocket(NetSocket socket) {
        if(socket != null) {
            try {
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
